#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

FILE *fopen(const char *path, const char *mode)
{
    FILE *f = NULL;
    int flags = 0;
    int plus = 0;
    int fd = 0;

    if (!path || *path == '\0')
    {
        errno = EINVAL;
        return NULL;
    }

    // parse mode string
    while (*mode)
    {
        // set mode
        switch (*mode)
        {
        case 'r':
            flags |= O_RDONLY;
            break;
        case 'w':
            flags |= O_WRONLY | O_CREATE | O_TRUNC;
            break;
        case 'a':
            flags |= O_WRONLY | O_CREATE | O_APPEND;
            break;
        case 'b':
            flags |= O_BINARY;
            break;
        case '+':
            plus = 1;
            break;
        default:
            break;
        }
        mode++;
    }
    if (plus)
    {
        flags = (flags & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
    }

    // open file
    fd = open(path, flags);
    if (fd < 0)
        return NULL;

    // alloc FILE
    f = __file_alloc(fd);
    if (!f)
    {
        close(fd);
        return NULL;
    }

    lseek(f->fd, 0, SEEK_SET);
    f->pos = 0;
    return f;
}
